#ifndef DEVICE_H
#define DEVICE_H

#include "global.h"
#include "freq_table.h"
#include "z_action.h"
#include "xy_action.h"

//------------------------------------------------------------------------------
// IO map
//------------------------------------------------------------------------------

sbit LED                        = P0^1; // 指示灯
sbit STEP1                      = P2^4; // 电机脉冲1
sbit STEP2                      = P2^5; // 电机脉冲2
sbit STEP3                      = P2^6; // 电机脉冲3
sbit DIR1                       = P1^7; // 电机方向1
sbit DIR2                       = P3^4; // 电机方向2
sbit EN1                        = P2^3; // 电机使能2
sbit XSEN                       = P1^1; // X左原点传感器
sbit YSEN                       = P1^5; // Y原点传感器
sbit ZSEN                       = P1^4; // Z原点传感器
sbit ZHOD                       = P1^3; // Z抓杯传感器
sbit ZLIM                       = P1^2; // Z抓杯到位传感器
#if (PCB_VERSION == PCB_A1)
sbit M1_1                       = P2^0; // 电机1细分1
sbit M1_2                       = P2^1; // 电机1细分2
sbit M1_3                       = P2^2; // 电机1细分3
sbit M2_1                       = P3^5; // 电机2细分1
sbit M2_2                       = P3^6; // 电机2细分2
sbit M2_3                       = P3^7; // 电机2细分3
sbit M3_1                       = P3^1; // 电机3细分1
sbit M3_2                       = P3^1; // 电机3细分2
sbit M3_3                       = P3^1; // 电机3细分3
#endif
sbit MAGENT                     = P1^0; // 电磁铁使能

#if (PCB_VERSION == PCB_A2)
sbit LOCK1                      = P2^0; // 电机1锁定信号
sbit LOCK2                      = P3^5; // 电机2锁定信号
#endif

#define BIT(n)                  (1 << (n))

#if (PCB_VERSION == PCB_A1)
// X电机细分配置
#define X_MOTOR_PORT                P4
#define X_M1                        BIT(2)
#define X_M2                        BIT(3)
#define X_M3                        BIT(4)
#define X_MOTOR_MASK                (X_M1 | X_M2 | X_M3)
#define X_MOTOR_EXCITATION_2        (0)
#define X_MOTOR_EXCITATION_8        (X_M3)
#define X_MOTOR_EXCITATION_10       (X_M2)
#define X_MOTOR_EXCITATION_16       (X_M2 | X_M3)
#define X_MOTOR_EXCITATION_20       (X_M1)
#define X_MOTOR_EXCITATION_32       (X_M1 | X_M3)
#define X_MOTOR_EXCITATION_40       (X_M1 | X_M2)
#define X_MOTOR_EXCITATION_64       (X_M1 | X_M2 | X_M3)

#define SET_X_MOTOR_EXCITATION(n)   do{X_MOTOR_PORT &= ~X_MOTOR_MASK; X_MOTOR_PORT |= (n);}while(0)

// Y电机细分配置
#define Y_MOTOR_PORT                P2
#define Y_M1                        BIT(0)
#define Y_M2                        BIT(1)
#define Y_M3                        BIT(2)
#define Y_MOTOR_MASK                (Y_M1 | Y_M2 | Y_M3)
#define Y_MOTOR_EXCITATION_2        (0)
#define Y_MOTOR_EXCITATION_8        (Y_M3)
#define Y_MOTOR_EXCITATION_10       (Y_M2)
#define Y_MOTOR_EXCITATION_16       (Y_M2 | Y_M3)
#define Y_MOTOR_EXCITATION_20       (Y_M1)
#define Y_MOTOR_EXCITATION_32       (Y_M1 | Y_M3)
#define Y_MOTOR_EXCITATION_40       (Y_M1 | Y_M2)
#define Y_MOTOR_EXCITATION_64       (Y_M1 | Y_M2 | Y_M3)

#define SET_Y_MOTOR_EXCITATION(n)   do{Y_MOTOR_PORT &= ~Y_MOTOR_MASK; Y_MOTOR_PORT |= (n);}while(0)

// Z电机细分配置
#define Z_MOTOR_PORT                P3
#define Z_M1                        BIT(7)
#define Z_M2                        BIT(6)
#define Z_M3                        BIT(5)
#define Z_MOTOR_MASK                (Z_M1 | Z_M2 | Z_M3)
#define Z_MOTOR_EXCITATION_2        (0)
#define Z_MOTOR_EXCITATION_8        (Z_M3)
#define Z_MOTOR_EXCITATION_10       (Z_M2)
#define Z_MOTOR_EXCITATION_16       (Z_M2 | Z_M3)
#define Z_MOTOR_EXCITATION_20       (Z_M1)
#define Z_MOTOR_EXCITATION_32       (Z_M1 | Z_M3)
#define Z_MOTOR_EXCITATION_40       (Z_M1 | Z_M2)
#define Z_MOTOR_EXCITATION_64       (Z_M1 | Z_M2 | Z_M3)

#define SET_Z_MOTOR_EXCITATION(n)   do{Z_MOTOR_PORT &= ~Z_MOTOR_MASK; Z_MOTOR_PORT |= (n);}while(0)
#endif

#define IO_X_HOME           (XSEN)
#define IO_X_STEP           STEP3
#define IO_X_ENABLE         EN3
#define IO_X_EN(n)          ((n) ? (P4 |= BIT(5)) : (P4 &= ~BIT(5)))
#define IO_X_DIR(n)         ((n) ? (P4 |= BIT(1)) : (P4 &= ~BIT(1)))

#define IO_Y_HOME           YSEN
#define IO_Y_STEP           STEP1
#define IO_Y_DIR            DIR1

#if (PCB_VERSION == PCB_A2)
#define IO_Y_EN(n)          EN1 = !n
#define IO_Y_LOCK(n)        LOCK1 = n
#else
#define IO_Y_EN(n)          EN1 = n
#endif

#define IO_Z_HOME           ZSEN
#define IO_Z_STEP           STEP2
#define IO_Z_DIR            DIR2

#if (PCB_VERSION == PCB_A2)
#define IO_Z_EN(n)          ((n == 0) ? (P4 |= BIT(0)) : (P4 &= ~BIT(0)))
#define IO_Z_LOCK(n)        LOCK2 = n
#else
#define IO_Z_EN(n)          ((n) ? (P4 |= BIT(0)) : (P4 &= ~BIT(0)))
#endif

#define X_AT_HOME           (!IO_X_HOME)
#define Y_AT_HOME           (!IO_Y_HOME)
#define Z_AT_HOME           (!IO_Z_HOME)

#if (PCB_VERSION == PCB_A2)
#define IO_M_HOME           (XSEN)
#define IO_M_STEP           STEP3
#define IO_M_ENABLE         EN3
#define IO_M_EN(n)          ((n == 0) ? (P4 |= BIT(5)) : (P4 &= ~BIT(5)))
#define IO_M_DIR(n)         ((n) ? (P4 |= BIT(1)) : (P4 &= ~BIT(1)))
#define IO_M_LOCK(n)        ((n) ? (P4 |= BIT(2)) : (P4 &= ~BIT(2)))
#define M_AT_HOME           (!IO_M_HOME)
#endif

#define IO_PICK_CUP          !ZLIM
#define IO_HOLDING_CUP       !ZHOD
#define IO_MAGENT            MAGENT

#define X_DIR_OUTPUT(dir)   (!(dir))                        // X方向位输出
#define Y_DIR_OUTPUT(dir)   (!(dir))                        // Y方向位输出
#define Z_DIR_OUTPUT(dir)   (!(dir))                        // Z方向位输出

#define MAGENT_OUTPUT(act)  (!(act))                        // 电磁铁输出

//------------------------------------------------------------------------------

// server_status定义
enum STATUS_CODE
{
    STATUS_IDLE = 0,
    STATUS_BUSY = 0xFFFF
};


// 电机碰到原点后运行的步数
#define Y_RESET_BUFFER_STEP     (MICROSTEP * 5)     // Y电机复位时, 经过原点后继续运行的步数
#define Y_LIMIT_BUFFER_STEP     (long)(Y_LIMIT_DISTANCE * SPR / Y_PERIMETER)// Y电机复位时, 经过原点后继续运行的步数
#define Z_RESET_BUFFER_STEP     (MICROSTEP * 5)     // Z电机复位时, 经过原点后继续运行的步数
#define Z_PROBE_BUFFER_STEP     200                 // z抓杯感应到信号时继续下探的步数
#define Z_RELEASE_BUFFER_STEP   200                 // z放杯感应到信号时继续下探的步数
// 抓杯时, 检测到抓杯信号后回退的步数
#define PICK_CUP_ROLLBACK_STEP  (long)(PICK_CUP_ROLLBACK * SPR / Z_PERIMETER)


#define Y_MAX_RESET_SPEED       4000

// Y移动一个定位销距离步数
#define Y_STEPS_BY_ONE_HOLE     (SPR * LOCATION_PERIMETER / Y_PERIMETER)

// 放杯到位检测传感器生效掩码
#define RELEASE_CUP_SENSOR_MASK     0x01UL

void Init_Device(void);
#define Update_WatchDog()       PCA0CPH5 = 0x00

// 系统时钟
#define US_TO_TICK_UL(us)       ((ulong)((us) * 1e-6 * SYSCLK / 12))    // 将us时间转换为定时器计数值, 最大32.767ms
#define US_TO_TICK(us)          ((ushort)US_TO_TICK_UL(us))
#define MS_TO_TICK_HIGH(ms)     ((ushort)(US_TO_TICK_UL((ms) * 1e3)/65536))
#define ONE_MS                  US_TO_TICK(1000)        // 1ms
#define TWO_MS                  US_TO_TICK(2000)        // 2ms
#define TEN_MS                  US_TO_TICK(10000)       // 10ms
#define _15_MS                  US_TO_TICK(15000)       // 15ms
#define TICK_TO_US(tick)        ((ulong)((tick)*(12e6/SYSCLK)))

ushort SystemTickLow();                         // 系统时钟低16位, X0.5us
ushort SystemTickHigh();                        // 系统时钟高16位, X32.768ms
ulong SystemTick();                             // 系统时钟, X0.5us
void Delay_Tick(ushort tick);
void Delay_Tick_Event(ulong tick);
#define Delay_us(n)                 Delay_Tick(US_TO_TICK(n))

extern uchar data server_address;       // 设备地址
extern bit pending_action;
extern bit ref_changed;                 // 参考坐标系改变
extern bit astar_map_changed;           // 地图数据已经改变, 需要重新建立

void Update_IO()reentrant;
void Update_Ref_Speed();
void Main_Loop();
void Process_Main_Loop();
void Process_Action();

#endif // DEVICE_H
